webSocket如何解决自动关闭的意思

您所在的位置:网站首页 小程序 websocket webSocket如何解决自动关闭的意思

webSocket如何解决自动关闭的意思

2023-09-08 05:12| 来源: 网络整理| 查看: 265

我的前一篇文章“webSocket如何在自己的工程中使用?”

地址:https://blog.csdn.net/jintingbo/article/details/80755636

讲述了webSocket的初级使用,初学者可以先看看那篇文章。

本文主要是解决webSocket自动关闭。

websocket它有一个“心跳”机制,但这个心跳机制是要程序自己去写代码实现的,websocket本身没有给你做这个东西。

它是如何自动关闭的呢?当电脑浏览器发送pong帧的时候,由于内容为空,于是服务器将空内容转发回去,导致客户端浏览器以为是错误的帧类型,发送关闭信息进行error关闭。(服务器返回时,必须要把它原来发来的东西发回去的,这是TCP/IP协议的要求)。

即然服务器接收到浏览器发送的"pong"后如果回复一个“pong”时,它会结束连接,那么为了避免这种事发生,可以在服务器接收到一个“pong”空信息时,不回复它的"pong",也就不关闭连接了。这是一种解决方案。

另一种解决方案是:当发生关闭时,可以主动发送心跳给对方,让连接复活,这样就相当于不断线了。本文就是用这个方案实现的。

第一步:在html文件中加入:-----------------------------

var ws; //避免重复连接 var lockReconnect = false; var wsUrl = "ws://localhost:8080/cl-market-camera-web/websocket"; createWebSocket(wsUrl); function createWebSocket(url) { try { ws = new WebSocket(url); initEventHandle(); } catch (e) {                        //重新连接 reconnect(url); } }        //封装websocket的那几个接口函数 function initEventHandle() { ws.onclose = function () { console.info("连接关闭"); reconnect(wsUrl); }; ws.onerror = function () { console.info("传输异常"); reconnect(wsUrl); }; ws.onopen = function () { //心跳检测重置 heartCheck.reset().start(); };

websocket.onmessage = function(event) {                    //console.info(event.data);

                    setMessageInnerHTML(event.data);                     //如果获取到消息,心跳检测重置                     heartCheck.reset().start(); } } function reconnect(url) { if(lockReconnect) return; lockReconnect = true; //没连接上会一直重连,设置延迟避免请求过多 setTimeout(function () {     console.info("尝试重连..." + new Date().format("yyyy-MM-dd hh:mm:ss"));     createWebSocket(url);     lockReconnect = false; }, 5000); } //心跳检测,每5s心跳一次 var heartCheck = { timeout: 5000, timeoutObj: null, serverTimeoutObj: null, reset: function(){     clearTimeout(this.timeoutObj);     clearTimeout(this.serverTimeoutObj);     return this;         }, start: function(){     var self = this;     this.timeoutObj = setTimeout(function(){         //这里发送一个心跳,后端收到后,返回一个心跳消息,         //onmessage拿到返回的心跳就说明连接正常         ws.send("HeartBeat" + new Date().format("yyyy-MM-dd hh:mm:ss"));                 console.info("客户端发送心跳:" + new Date().format("yyyy-MM-dd hh:mm:ss"));

                self.serverTimeoutObj = setTimeout(function(){                            //如果超过一定时间还没重置,说明后端主动断开了

                            ws.close();                            //如果onclose会执行reconnect,我们执行ws.close()就行了.                             //如果直接执行reconnect 会触发onclose导致重连两次                         }, self.timeout)                     }, this.timeout)                 } } //js中格式化日期,调用的时候直接:new Date().format("yyyy-MM-dd hh:mm:ss") Date.prototype.format = function(fmt) { var o = {     "M+" : this.getMonth()+1,                 //月份      "d+" : this.getDate(),                    //日      "h+" : this.getHours(),                   //小时      "m+" : this.getMinutes(),                 //分      "s+" : this.getSeconds(),                 //秒      "q+" : Math.floor((this.getMonth()+3)/3), //季度     "S"  : this.getMilliseconds()             //毫秒          };          if(/(y+)/.test(fmt)) {

    fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 

                }

        for(var k in o) {     if(new RegExp("("+ k +")").test(fmt)){         fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));             }                }         return fmt;         } function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + ''; }

第二步:在java的controller包中写一个WebSocketTest类------------------------------package com.clmarket.controller;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.concurrent.CopyOnWriteArraySet;@ServerEndpoint("/websocket")public class WebSocketTest {        //设置连接数 private static int onlineCount = 0; private static CopyOnWriteArraySet webSocketSet =  new CopyOnWriteArraySet(); private Session session; public Session getSession(){ return this.session; } @OnOpen public void onOpen(Session session){ this.session = session; webSocketSet.add(this);     //加入set中 addOnlineCount();           //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); } @OnClose public void onClose(){ webSocketSet.remove(this);  //从set中删除 subOnlineCount();           //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 服务器向浏览器发送消息 * @param message 需要推送到浏览器的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String message, Session session) { for(WebSocketTest item: webSocketSet){ try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } } } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ System.out.println("发生错误"); error.printStackTrace(); } /** * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketTest.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketTest.onlineCount--; }

}

第三步:如何把自己的信息借助上面的WebSocketTest类推送出去-----------------------------

比如服务器有一个字符串“鄂H AAAAA8”这样的字符串,要把它推到浏览器里显示出来,

其实只要三句话搞定:

String license=“鄂H AAAAA8”;

//new一个WebSocketTest对象,表示我要用它来发送WebSocketTest wst=new WebSocketTest();//这个session实际上是import javax.websocket.Session;Session session=wst.getSession();//调用这个webSocketTest对象的onMessage就可以把license发送出去了。wst.onMessage(license, session);

全文完:湖北荆门金庭波 QQ:14280784 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3